package org.pt.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import lombok.extern.slf4j.Slf4j;
import org.pt.components.Response;
import org.pt.dto.*;
import org.pt.exception.InvitationException;
import org.pt.exception.LoginException;
import org.pt.exception.RegisterException;
import org.pt.exception.UserException;

import org.pt.service.impl.UserServiceImpl;
import org.pt.utils.JwtToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;


@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserServiceImpl userServiceImpl;


    @Operation(
            summary = "用户注册",
            description = "用于用户注册，接收用户基本信息和头像文件"
    )
    @Parameters({
            @Parameter(
                    name = "metadata",
                    description = "用户注册信息",
                    required = true,
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = RegisterDto.class)
                    )
            ),
            @Parameter(
                    name = "avatar",
                    description = "用户头像文件",
                    schema = @Schema(type = "string", format = "binary")
            )
    })
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "成功",content = @Content(schema = @Schema(implementation = Response.class),mediaType = MediaType.APPLICATION_JSON_VALUE)),
            @ApiResponse(
                    responseCode = "504",
                    description = "注册错误，具体描述见msg",
                    content = @Content(schema = @Schema(implementation = Response.class),mediaType = MediaType.APPLICATION_JSON_VALUE)
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "邀请码错误，具体描述见msg",
                    content = @Content(schema = @Schema(implementation = Response.class),mediaType = MediaType.APPLICATION_JSON_VALUE)
            )
    })
    @PostMapping(value = "register", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Response<String> register(
            @RequestPart("metadata") RegisterDto registerDto,
            @RequestPart(value = "avatar", required = false) MultipartFile avatar) throws RegisterException, InvitationException, IOException {
        return userServiceImpl.register(registerDto,avatar);
    }


    @Operation(
            summary = "获取用户头像",
            description = "根据头像路径返回用户头像图片字节流，需要认证访问",
            parameters = {
                    @Parameter(
                            name = "avatarPath",
                            description = "头像文件路径（可选），不传则使用默认头像",
                            example = "avatar/user123.png",
                            in = ParameterIn.QUERY
                    ),
                    @Parameter(
                            name = "Authorization",
                            description = "认证token",
                            required = true,
                            in = ParameterIn.HEADER,
                            example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                    )
            },
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "成功获取头像",
                            content = @Content(
                                    mediaType = "image/jpeg",
                                    schema = @Schema(type = "string", format = "binary")
                            )
                    )
            }
    )
    @GetMapping("getUserAvatar")
    public ResponseEntity<byte[]> getUserAvatar(@RequestParam String avatarPath) throws IOException {
        if(avatarPath==null || avatarPath.isEmpty())
        {
            avatarPath="avatar/default.png";
        }
        File file = new File(avatarPath);
        byte[] imageBytes = Files.readAllBytes(file.toPath());
        // 构建 HTTP 响应头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);
        headers.setContentLength(imageBytes.length);
        // 返回包含图片字节数组的 ResponseEntity
        return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
    }


    @Operation(
            summary = "获取用户信息",
            description = "获取用户信息，需要认证访问",
            parameters = {
                    @Parameter(
                            name = "Authorization",
                            description = "认证token",
                            required = true,
                            in = ParameterIn.HEADER,
                            example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                    )
            },
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "成功获取头像",
                            content = @Content(
                                    mediaType = MediaType.APPLICATION_JSON_VALUE,
                                    schema = @Schema(implementation = UserInfoDto.class)
                            )
                    )
            }
    )
    @GetMapping("getUserInfo")
    public Response<UserInfoDto> getUsers(@RequestHeader("Authorization") String token) throws UserException {
        int userId=JwtToken.getId(token);
        return userServiceImpl.getUserInfo(userId);
    }

    @GetMapping("getPasskey")
    public Response<String> getUserPasskey(@RequestHeader("Authorization") String token) throws UserException {
        int userId=JwtToken.getId(token);
        return userServiceImpl.getUserPasskey(userId);
    }

    @Operation(
            summary = "获取验证码",
            description = "根据用户名和邮箱地址发送验证码，可用于登录/注册场景",
            parameters = {
                    @Parameter(
                            name = "username",
                            description = "用户名",
                            required = true,
                            example = "john_doe",
                            in = ParameterIn.QUERY
                    ),
                    @Parameter(
                            name = "emailAddr",
                            description = "邮箱地址",
                            required = true,
                            example = "user@example.com",
                            in = ParameterIn.QUERY
                    ),
                    @Parameter(
                            name = "isLogin",
                            description = "验证码用途类型：1-登录，0-注册",
                            required = true,
                            example = "1",
                            in = ParameterIn.QUERY,
                            schema = @Schema(type = "integer", allowableValues = {"0", "1"})
                    )
            },
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "验证码发送成功",
                            content = @Content(
                                    mediaType = "application/json",
                                    schema = @Schema(
                                            type = "object",
                                            description = "返回包含邮箱和验证码的映射",
                                            example = """
                        {
                          "code": 200,
                          "message": "success",
                          "data": {
                            "email": "user@example.com",
                            "verifyCode": "123456"
                          }
                        }
                        """
                                    )
                            )
                    )
            }
    )
    @GetMapping("verifyCode")
    public Response<Map<String,String>> verifyCode(@RequestParam String username,@RequestParam String emailAddr,@RequestParam int isLogin) throws LoginException, RegisterException {
        return userServiceImpl.getVerifyCode(username,emailAddr,isLogin);
    }

    @Operation(
            summary = "用户登录",
            description = "通过用户名/密码进行系统登录",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "登录凭证",
                    required = true,
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = LoginDto.class)
                    )
            )
    )
    @ApiResponses({
            @ApiResponse(
                    responseCode = "200",
                    description = "success",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = LoginResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "503",
                    description = "登录错误，具体原因见msg",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Response.class)

                    )
            )
    })
    @PostMapping("login")
    public Response<LoginResponseDto> login(@RequestBody LoginDto loginDto) throws LoginException {
        return userServiceImpl.login(loginDto);
    }

    @GetMapping("getInvitationCode")
    @Operation(
            summary = "获取邀请码",
            description = "根据剩余可用次数生成邀请码（需要管理员可生成多个，普通用户可生成一个，一个人允许有一个邀请码）",
            parameters = {
                    @Parameter(
                            name = "remaining",
                            description = "邀请码剩余可用次数，普通用户只能1次，管理员可多次",
                            required = true,
                            example = "5",
                            schema = @Schema(type = "integer", minimum = "1", maximum = "100")
                    )
            }
    )
    @ApiResponses({
            @ApiResponse(
                    responseCode = "200",
                    description = "获取成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = InvitationDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "301，302，303",
                    description = "token不通过，具体见msg描述",
                    content = @Content(
                    mediaType = MediaType.APPLICATION_JSON_VALUE
            )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "邀请码已存在",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE
                    )
            )
    })
    public Response<InvitationDto> getInvitationCode(
            @Parameter(
                    description = "认证令牌",
                    required = true,
                    example = "eyJhbGciOi...",
                    in = ParameterIn.HEADER
            )
            @RequestHeader("Authorization") String token,

            @RequestParam int remaining
    )  throws InvitationException
    {
        Integer id=JwtToken.getId(token);
        Boolean isAdmin=JwtToken.isAdmin(token);
        return userServiceImpl.getInvitationCode(id,remaining,isAdmin);
    }

    @Operation(
            summary = "更新用户信息",
            description = "部分更新用户个人信息，所有字段均为可选",
            parameters = {
                    @Parameter(
                            name = "Authorization",
                            description = "认证token",
                            required = true,
                            in = ParameterIn.HEADER,
                            example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                    )
            },
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "更新用户信息DTO",
                    required = true,
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = UpdateInfoDto.class)
                    )
            ),
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "更新成功",
                            content = @Content(
                                    mediaType = "application/json",
                                    schema = @Schema(
                                            description = "返回更新成功的字段列表",
                                            example = """
                        {
                          "code": 200,
                          "message": "success",
                          "data": ["bio", "school"]
                        }
                        """
                                    )
                            )
                    )
            }
    )
    @PostMapping("updateInfo")
    public Response<List<String>> updateInfo(@RequestBody UpdateInfoDto updateInfoDto) throws UserException {
        return userServiceImpl.updateUserInfo(updateInfoDto);
    }


}
